package com.hengxinyongli.iam.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.hengxinyongli.iam.dto.Subject;
import com.hengxinyongli.iam.exception.IamTokenCreateException;
import com.hengxinyongli.iam.exception.IamTokenVerifyException;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.util.Calendar;

/**
 * @author magic
 * @date 2018/9/27/027 14:45
 * @version 1.0
 * Description JwtAuthService
 */
@Component
public class JwtAuthService {

    Logger LOG = LoggerFactory.getLogger(JwtAuthService.class);

    @Value("${jwt.sec.key:123456}")
    private String securityKey;

    @Value("${jwt.sec.times:1800}")
    private int times;

    private static final String USER_ID = "uid";
    private static final String USER_NAME = "un";
    private static final String USER_MOBILE = "mb";
    private static final String USER_TYPE = "utp";
    private static final String USER_DEP = "dpi";
    private static final String USER_DEP_LABEL = "dpb";

    public String createJwtToken(Subject subject){
        try {
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.SECOND,times);
            Algorithm algorithm = Algorithm.HMAC256(securityKey);
            String token = JWT.create()
                    .withClaim(USER_ID,subject.getUserId())
                    .withClaim(USER_NAME,subject.getUserName())
                    .withClaim(USER_MOBILE,subject.getMobile())
                    .withClaim(USER_TYPE,subject.getUserType())
                    .withClaim(USER_DEP,subject.getDepId())
                    .withClaim(USER_DEP_LABEL,subject.getDepLabel())
                    .withExpiresAt(calendar.getTime())
                    .sign(algorithm);
            return token;
        } catch (JWTCreationException | UnsupportedEncodingException e){
            LOG.error("IAM Create UserToken Exception: {}", ExceptionUtils.getRootCauseMessage(e));
            throw new IamTokenCreateException("IAM生成token异常" ,e);
        }
    }

    public Subject parseJwtToken(String jwtToken){
        try {
            Algorithm algorithm = Algorithm.HMAC256(securityKey);
            JWTVerifier verifier = JWT.require(algorithm)
                    .build(); //Reusable verifier instance
            DecodedJWT jwt = verifier.verify(jwtToken);
            Subject subject = new Subject();
            subject.setUserId(jwt.getClaim(USER_ID).asLong());
            subject.setUserName(jwt.getClaim(USER_NAME).asString());
            subject.setMobile(jwt.getClaim(USER_MOBILE).asString());
            subject.setUserType(jwt.getClaim(USER_TYPE).asString());
            subject.setDepId(jwt.getClaim(USER_DEP).asString());
            subject.setDepLabel(jwt.getClaim(USER_DEP_LABEL).asString());
            return subject;
        } catch (JWTVerificationException | UnsupportedEncodingException e){
            LOG.error("IAM Verification UserToken Exception: {}", ExceptionUtils.getRootCauseMessage(e));
            throw new IamTokenVerifyException("UserToken 过期已失效" ,e);
        }
    }

}
